package com.hugoo.core.util;

import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.nio.channels.FileChannel;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 *
 * @author Hugoo.Chan
 */
public class TL {

    private final static Log log = LogFactory.getLog(TL.class);

    public static boolean isMatch(String org, String pat) {
        if (TL.isEmpty(org, pat)) {
            return false;
        }
        return org.matches(pat);
    }

    public static Integer parseInt(String vl) {
        return parseInt(vl, null);
    }

    public static Integer parseInt(String vl, Integer defvla) {
        Double dbl;
        if (defvla == null) {
            dbl = parseDouble(vl);
        } else {
            dbl = parseDouble(vl, new Double(defvla));
        }
        if (dbl == null) {
            return null;
        }
        return dbl.intValue();
    }

    public static Double parseDouble(String vl) {
        return parseDouble(vl, null);
    }

    public static Double parseDouble(String vl, Double defvla) {
        if (TL.isEmpty(vl)) {
            return defvla;
        }
        Double d = null;
        try {
            d = Double.parseDouble(vl.replaceAll("[^0-9\\-.]", ""));
        } catch (Exception e) {
            log.info("解析字符串【" + vl + "】为Double类型失败，现返回缺省值【" + defvla + "】！", e);
            d = defvla;
        } finally {
            return d;
        }
    }

    public static boolean isNotEmpty(String... tmp) {
        return !isEmpty(tmp);
    }

    public static String format(Date date, String pattern) {
        DateFormat format = new SimpleDateFormat(pattern);
        return format.format(date);
    }

    public static String decode(String str) {
        return null;
    }

    public static String encode(String str) {
        return null;
    }

    public static boolean isEmpty(String... tmp) {
        if (tmp == null || tmp.length == 0) {
            return true;
        }
        for (String t : tmp) {
            if (t == null) {
                return true;
            }
            if (t.trim().length() < 1) {
                return true;
            }
        }
        return false;
    }

    public static boolean isNaN(String ps) {
        if (isEmpty(ps)) {
            return true;
        }
        if (ps.matches("^\\d+(\\.\\d+)?$")) {
            return false;
        }
        return true;
    }

    public static String socd() {
        return LxString.scod();
    }
    private static final String CODING = "UTF-8";

    public static void parseParaUpper(String url, Map<String, String> para, Log log) {
        TL.parsePara(url, para, log, true);
    }

    public static void parsePara(String url, Map<String, String> para, Log log) {
        TL.parsePara(url, para, log, false);
    }

    /**
     * 处理参数程序，本部分主要是针对传入的参数做数据上的处理操作
     *
     * @param url
     */
    private static void parsePara(String url, Map<String, String> para, Log log, boolean isUpper) {
        if (TL.isNotEmpty(url)) {//处理传入参数
            try {
                url = URLDecoder.decode(url, CODING);
            } catch (UnsupportedEncodingException ex) {
                log.info("由于转码问题，不能正确的处理转入的参数部分！程序不能正常的工作哦~" + url);
                return;
            }
            String[] z, pz = url.split("&");
            for (String p : pz) {
                if (TL.isEmpty(p)) {//过滤掉数据无效部分
                    continue;
                }
                z = p.split("=");
                if (z.length > 2) {
                    log.info("无法解析本文本:" + p);
                } else {
                    if (z.length < 2) {//当传入的值为空时，视为无效节点
//                        log.info("本节点无效");
                        continue;
                    }
                    if (isUpper) {
                        para.put(z[0].toUpperCase(), z[1].replace("'", "''"));//本处处理传入数据特殊情况（单引）
                    } else {
                        para.put(z[0], z[1].replace("'", "''"));//本处处理传入数据特殊情况（单引）
                    }
                }
            }
            log.info("解析出以下参数值：" + para);
        }
    }

    public static void copyFile(File o, File n) {
        int length;
        try {
            FileInputStream in = new FileInputStream(o);
            FileOutputStream out = new FileOutputStream(n);
            FileChannel inC = in.getChannel();
            FileChannel outC = out.getChannel();
            int i = 0;
            while (true) {
                if (inC.position() == inC.size()) {
                    inC.close();
                    outC.close();
                    break;
                }
                if ((inC.size() - inC.position()) < 20971520) {
                    length = (int) (inC.size() - inC.position());
                } else {
                    length = 20971520;//2M
                }
                inC.transferTo(inC.position(), length, outC);
                inC.position(inC.position() + length);
                i++;
            }
        } catch (Exception e) {
            log.warn("复制文件出错！", e);
        }
    }

    public static String fileToStr(String fileName) {
        File file = new File(fileName);
        if (!file.exists() && !file.canRead()) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        int i1, i2, ch;
        char A1, A2;
        InputStream is = null;
        try {
            is = new FileInputStream(file);
            while ((ch = is.read()) != -1) {
                i1 = ch % 16;
                if (i1 > 9) {
                    i1 = i1 + 55;
                } else {
                    i1 = i1 + 48;
                }
                A1 = (char) i1;

                i2 = ch / 16;
                if (i2 > 9) {
                    i2 = i2 + 55;
                } else {
                    i2 = i2 + 48;
                }
                A2 = (char) i2;

                sb.append(String.valueOf(A2)).append(String.valueOf(A1));
            }
        } catch (Exception e) {
            log.warn("文件转文本出现异常！", e);
        } finally {
            TL.close(is);
        }
        return sb.toString();
    }

    public static void close(Object... rs) {
        for (Object o : rs) {
            if (o == null) {
                continue;
            }
            try {
                if (o instanceof ResultSet) {
                    ((ResultSet) o).close();
                } else if (o instanceof Statement) {
                    ((Statement) o).close();
                } else if (o instanceof Connection) {
                    ((Connection) o).close();
                } else if (o instanceof Closeable) {
                    ((Closeable) o).close();
                }
            } catch (Exception e) {
                log.info("关闭对象出现异常！", e);
            }
        }
    }

    /**
     * 用于解决XML HTML等标识文件的数据显示问题
     *
     * @param string
     * @return
     */
    public static String escape(String string) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0, length = string.length(); i < length; i++) {
            char c = string.charAt(i);
            switch (c) {
                case '&':
                    sb.append("&amp;");
                    break;
                case '<':
                    sb.append("&lt;");
                    break;
                case '>':
                    sb.append("&gt;");
                    break;
                case '"':
                    sb.append("&quot;");
                    break;
                case '\'':
                    sb.append("&apos;");
                    break;
                case '\n':
                case 13:
                    sb.append("");
                    break;
                default:
                    sb.append(c);
            }
        }
        return sb.toString();
    }

    /**
     * 针对字符串做JSON序列化处理
     *
     * @param string
     * @return 返回的是一个处理完成的JSON序列化语句
     */
    public static String quote(String string) {
        if (string == null || string.length() == 0) {
            return "\"\"";
        }

        char b;
        char c = 0;
        String hhhh;
        int i;
        int len = string.length();
        StringBuilder sb = new StringBuilder();
        sb.append('"');
        for (i = 0; i < len; i += 1) {
            b = c;
            c = string.charAt(i);
            switch (c) {
                case '\\':
                case '"':
                    sb.append('\\').append(c);
                    break;
                case '/':
                    if (b == '<') {
                        sb.append('\\');
                    }
                    sb.append(c);
                    break;
                case '\b':
                    sb.append("\\b");
                    break;
                case '\t':
                    sb.append("\\t");
                    break;
                case '\n':
                    sb.append("\\n");
                    break;
                case '\f':
                    sb.append("\\f");
                    break;
                case '\r':
                    sb.append("\\r");
                    break;
                default:
                    if (c < ' ' || (c >= '\u0080' && c < '\u00a0')
                            || (c >= '\u2000' && c < '\u2100')) {
                        sb.append("\\u");
                        hhhh = Integer.toHexString(c);
                        sb.append("0000", 0, 4 - hhhh.length());
                        sb.append(hhhh);
                    } else {
                        sb.append(c);
                    }
            }
        }
        sb.append('"');
        return sb.toString();
    }

    /**
     * 高效的字符串替代函数，性能高过JAVA API中的replaceAll函数 注：本函数不知道正则表达式，在处理正则表达式数据时，请采用自带函数
     *
     *
     * @param strSource
     * @param strFrom
     * @param strTo
     * @return
     */
    public static String replace(String strSource, String strFrom, String strTo) {
        if (strSource == null) {
            return null;
        }
        int i = 0;
        if ((i = strSource.indexOf(strFrom, i)) >= 0) {
            char[] cSrc = strSource.toCharArray();
            char[] cTo = strTo.toCharArray();
            int len = strFrom.length();
            StringBuilder buf = new StringBuilder(cSrc.length);
            buf.append(cSrc, 0, i).append(cTo);
            i += len;
            int j = i;
            while ((i = strSource.indexOf(strFrom, i)) > 0) {
                buf.append(cSrc, j, i - j).append(cTo);
                i += len;
                j = i;
            }
            buf.append(cSrc, j, cSrc.length - j);
            return buf.toString();
        }
        return strSource;
    }

    public static void main(String[] args) {
        String x = "CM01";
        for (int i = 0; i < 120; i++) {
            x = nextCode(x, "LTR");
            System.out.println(x);
        }
    }

    public static String nextCode(String code, String stpe) {
        code = code.toUpperCase();
        char cr[] = code.toCharArray(), RD = "NUM".equalsIgnoreCase(stpe) ? '9' : 'Z', LD = "LTR".equalsIgnoreCase(stpe) ? 'A' : '0';
        for (int x = cr.length - 1; x > -1; x--) {
            if (cr[x] < RD) {
                char xe;
                if (cr[x] == '9' || (LD == 'A' && cr[x] < '9')) {
                    xe = 'A';
                } else {
                    xe = (char) (cr[x] + 1);
                }
                String c = new String(Arrays.copyOfRange(cr, x + 1, cr.length));
                return code.substring(0, x) + xe + c;
            } else {
                cr[x] = LD;
            }
        }

        return code;
    }

    public static String nextCode(String code) {
        return nextCode(code, "ALL");
    }

    public static String numFmt(Number nb, NumFmt nf) {
        switch (nf) {
            case PCT:
                return pct.format(nb);
            case RMB:
                return rmb.format(nb);
            case DBL2:
                return fmdb2.format(nb);
            case DBL4:
                return fmdb4.format(nb);
            case NUM:
                return numf.format(nb);
        }
        return nb.toString();
    }

    public enum NumFmt {

        PCT, RMB, DBL2, DBL4, NUM
    }
    static final DecimalFormat pct = new DecimalFormat("0.00%"),
            numf = new DecimalFormat("##0.##"),
            fmdb4 = new DecimalFormat("##0.0000"),
            fmdb2 = new DecimalFormat("###0.00"),
            rmb = new DecimalFormat("#,##0.00");
}
